package com.gridmobi.xrtb.job;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.gridmobi.xrtb.component.lucene.BidIndex;
import com.gridmobi.xrtb.domain.dsp.*;
import com.gridmobi.xrtb.domain.dsp.common.OpenApiParamDTO;
import com.gridmobi.xrtb.domain.dsp.common.OpenApiResponseDTO;
import com.gridmobi.xrtb.handler.DataSynchHandler;
import com.gridmobi.xrtb.handler.ImprOffersHandler;
import com.gridmobi.xrtb.handler.monitor.RtbStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * RTB实时数据更新 以及reindex
 *
 * @author huangyongchao
 */
@Component
public class DataSynchJob {
    private static final Logger logger = LoggerFactory.getLogger(DataSynchJob.class);


    public final static long DELAY_SECOND = 1 * 1000 * 300;
    public final static long DELAY_MIN = 1 * 1000 * 1200;


    @Autowired
    private DataSynchHandler dataSynch;

    @Autowired
    private BidIndex bidIndex;

    @Autowired
    SourceManager sourceManager;

    private Date schynCampStart;
    private Date schynCfgStart;
    private Date schynBannerStart;


    private Date schynRulesStart;
    private Date schynMicrobidStart;
    private Date schynBlockListStart;
    @PostConstruct
    public void start(){
        synchOffers();
    }
    /**
     * 系统启动需要执行的任务可以在这里调用
     * 如果时间间隔很短的比如每秒执行一次的无需添加
     */

    @Scheduled(cron = "0 */3 *  * * ?")
    public void synchOffers() {

        OpenApiParamDTO param = new OpenApiParamDTO();

        OpenApiResponseDTO resp = dataSynch.synchOffers(param);

        if (resp != null && !CollectionUtils.isEmpty(resp.getDatas())) {
            List<JOffer> lists = Lists.newLinkedList();
            resp.getDatas().forEach(n -> {
                JOffer o = JSONObject.parseObject(JSONObject.toJSONString(n), JOffer.class);
                o.setCountries(o.getCountries().toUpperCase(Locale.ROOT));
                o.setOs(o.getOs().toLowerCase());
                lists.add(o);
            });

            logger.info("Data Synch synchOffers  ", resp.getDatas().size());
            Map<String, List<JOffer>> geo_m = lists.stream().collect(Collectors.groupingBy(JOffer::getCountries));
            Map<String, List<JOffer>> geo_os_offer = Maps.newHashMap();
            geo_m.forEach((geo, v) -> {
                Map<String, List<JOffer>> os_m = v.stream().collect(Collectors.groupingBy(JOffer::getOs));
                os_m.forEach((os, list) -> {
                    List<JOffer> newList = Lists.newArrayList();
                    list.forEach(n->{
                        int l = n.getDailymaxclicks() / 100000;
                        for(int i=0;i<=l ;i++){
                            newList.add(n);
                        }
                    });
                    geo_os_offer.put(geo + os, newList);
                });

            });
            ImprOffersHandler.GEO_OS_MAP = geo_os_offer;
            System.out.println(JSONObject.toJSONString(geo_os_offer));
        }
        logger.info("synch synchOffers over");
    }

    @Scheduled(cron = "0 */30 *  * * ?")
    public void synchCampaignTrend() {
        /*Map<String, Map<String, DspTrend>> concurrentHashMap = Maps.newConcurrentMap();
        Map<String, Map<String, Map>> trend = dataSynch.synchCampaignTrend();
        if (trend != null) {
            trend.forEach((cid, map) -> {
                Map<String, DspTrend> htrend = Maps.newHashMap();
                List<Float> sumList = Lists.newLinkedList();
                map.forEach((h, ctrend) -> {
                    DspTrend dspTrend = JSONObject.parseObject(JSONObject.toJSONString(ctrend), DspTrend.class);
                    htrend.put(h, dspTrend);
                    sumList.add(dspTrend.getWinrate());
                });
                concurrentHashMap.put(cid, htrend);

            });
        }

        logger.info("synch ctrend over");*/
    }

    @Scheduled(fixedDelay = DELAY_SECOND)
    public void synchCampaigns() {
        if (!RtbStatus.INDEX_INIT_FINISHED.get()) {
            return;
        }
        try {
            OpenApiParamDTO param = new OpenApiParamDTO();
            Date endTimestamp = new Date(LocalDateTime.now().plusMinutes(-1).toInstant(ZoneOffset.UTC).toEpochMilli());
            if (schynCampStart == null) {
                schynCampStart = InitIndexJob.INDEX_INIT_TIMESTAMP_END;
            }
            param.setPage(1);
            param.setSize(InitIndexJob.DATA_QUERY_PAGESIZE);
            param.setStart(schynCampStart);
            param.setEnd(endTimestamp);
            OpenApiResponseDTO<DspCampaigns> resp = dataSynch.synchCampaigns(param);
            if (resp != null && !CollectionUtils.isEmpty(resp.getDatas())) {
                logger.info("Data Synch Campaigns  ", resp.getDatas().size());

                bidIndex.indexCampaigns(resp.getDatas());

                //
                // schynCampStart = endTimestamp;
            }
        } catch (Exception e) {
            logger.error("Data Synch Error ", e);
            RtbStatus.errorCounter();
        }

    }

    @Scheduled(fixedDelay = DELAY_SECOND)
    public void synchCreatives() {
        if (!RtbStatus.INDEX_INIT_FINISHED.get()) {
            return;
        }
        try {
            OpenApiParamDTO param = new OpenApiParamDTO();
            Date endTimestamp = new Date(LocalDateTime.now().plusMinutes(-1).toInstant(ZoneOffset.UTC).toEpochMilli());
            if (schynBannerStart == null) {
                schynBannerStart = InitIndexJob.INDEX_INIT_TIMESTAMP_END;
            }
            param.setPage(1);
            param.setSize(InitIndexJob.DATA_QUERY_PAGESIZE);
            param.setStart(schynBannerStart);
            param.setEnd(endTimestamp);

            // 图片资源
            List<DspCreativeBanner> dspCreativeBanners = dataSynch.synchCreativeBanner(param);
            bidIndex.indexCreatives(dataSynch.convertBannerList(dspCreativeBanners));
            sourceManager.syncImgSource(dspCreativeBanners);

            // video 资源
            List<DspCreativeVideo> dspCreativeVideos = dataSynch.synchCreativeVideo(param);
            bidIndex.indexCreatives(dataSynch.convertVideoList(dspCreativeVideos));
            sourceManager.syncVideoSource(dspCreativeVideos);

            bidIndex.indexCreatives(dataSynch.convertHtmlList(dataSynch.synchCreativeHtml(param)));
            List<DspCreativeNative> dspCreativeNatives = dataSynch.synchCreativeNative(param);
            bidIndex.indexCreativesNative(dspCreativeNatives);
            sourceManager.syncNativeSource(dspCreativeNatives);

            schynBannerStart = endTimestamp;

        } catch (Exception e) {
            logger.error("Data Synch Error ", e);
            RtbStatus.errorCounter();

        }
    }


    @Scheduled(fixedDelay = DELAY_MIN)
    public void synchMicro() {
        if (!RtbStatus.INDEX_INIT_FINISHED.get()) {
            return;
        }
        try {
            OpenApiParamDTO param = new OpenApiParamDTO();
            Date endTimestamp = new Date(LocalDateTime.now().plusMinutes(-1).toInstant(ZoneOffset.UTC).toEpochMilli());
            if (schynMicrobidStart == null) {
                schynMicrobidStart = InitIndexJob.INDEX_INIT_TIMESTAMP_END;
            }
            param.setPage(1);
            param.setSize(InitIndexJob.DATA_QUERY_PAGESIZE);
            param.setStart(schynMicrobidStart);
            param.setEnd(endTimestamp);

            OpenApiResponseDTO responseDTO = dataSynch.synchMicroBid(param);
            if (responseDTO != null) {

                bidIndex.indexMicroBid(responseDTO.getDatas());
            }

            schynMicrobidStart = endTimestamp;

        } catch (Exception e) {
            logger.error("Data Synch Error ", e);
            RtbStatus.errorCounter();

        }
    }

    @Scheduled(fixedDelay = DELAY_MIN)
    public void synchBlockList() {
        if (!RtbStatus.INDEX_INIT_FINISHED.get()) {
            return;
        }
        try {
            OpenApiParamDTO param = new OpenApiParamDTO();
            Date endTimestamp = new Date(LocalDateTime.now().plusMinutes(-1).toInstant(ZoneOffset.UTC).toEpochMilli());
            if (schynBlockListStart == null) {
                schynBlockListStart = InitIndexJob.INDEX_INIT_TIMESTAMP_END;
            }
            param.setPage(1);
            param.setSize(InitIndexJob.DATA_QUERY_PAGESIZE);
            param.setStart(schynBlockListStart);
            param.setEnd(endTimestamp);

            OpenApiResponseDTO responseDTO = dataSynch.synchBlocklist(param);
            if (responseDTO != null) {

                bidIndex.indexBlockList(responseDTO.getDatas());
            }

            schynBlockListStart = endTimestamp;

        } catch (Exception e) {
            logger.error("Data Synch Error ", e);
            RtbStatus.errorCounter();

        }
    }

}
